package main

import (
    "encoding/json"
    "fmt"
    "strconv"
)



type Actions []*Action

func (c Actions) Len() int {
    return len(c)
}
func (c Actions) Swap(i, j int) {
    c[i], c[j] = c[j], c[i]
}
func (c Actions) Less(i, j int) bool {
    return c[i].Offset < c[j].Offset
}

type Action struct {
    Namespace  string            `json:"namespace,omitempty"`
    Path       string            `json:"path,omitempty"`
    Properties map[string]string `json:"props,omitempty"`
    ActionType ActionType        `json:"action_type,omitempty"`
    Version    string            `json:"version,omitempty"`
    Offset     uint64            `json:"global_offset,omitempty"`
    CreateTime int64             `json:"create_time,omitempty"`
}

func EmptyAction() *Action {
    return &Action{
        Properties: make(map[string]string),
    }
}

func (ac *Action) Ready() bool {
    return ac.Offset != 0
}

func LoadActionFromProperties(prop map[string]string) error {
    ac := EmptyAction()
    for k, v := range prop {
        switch k {
        case KEY_NAMESPACE:
            ac.Namespace = v
            delete(prop, k)
        case KEY_PATH:
            ac.Path = v
        case KEY_ACTION_TYPE:
            t, err := ParseActionType(v)
            if err != nil {
                return err
            }
            ac.ActionType = t
            delete(prop, k)
        case KEY_VERSION:
            ac.Version = v
            delete(prop, k)
        case KEY_OFFSET:
            o, err := strconv.ParseUint(v, 10, 64)
            if err != nil {
                return err
            }
            ac.Offset = o
            delete(prop, k)
        case KEY_CREATE_TIME:
            t, err := strconv.ParseInt(v, 10, 64)
            if err != nil {
                return err
            }
            ac.CreateTime = t
            delete(prop, k)
        }
        ac.Properties = prop
    }
    return nil
}

func (ac *Action) ToProperties() (map[string]string, error) {
    ret := make(map[string]string)
    ret[KEY_NAMESPACE] = ac.Namespace
    ret[KEY_PATH] = ac.Path
    for k, v := range ac.Properties {
        ret[k] = v
    }
    ret[KEY_ACTION_TYPE] = fmt.Sprintf("%d", ac.ActionType)
    ret[KEY_VERSION] = ac.Version
    ret[KEY_OFFSET] = fmt.Sprintf("%d", ac.Offset)
    ret[KEY_CREATE_TIME] = fmt.Sprintf("%d", ac.CreateTime)
    return ret, nil
}


func (ac *Action) Load(b []byte) error {
    return json.Unmarshal(b, ac)
}
func (ac *Action) Value() ([]byte, error) {
    if ac.Namespace == "" || ac.Path == "" || ac.Version == "" {
        return nil, fmt.Errorf("missing key field in action")
    }
    return json.Marshal(ac)
}
